package com.lw.sbdemo2.common.utils;

import com.lw.sbdemo2.common.exception.ApiException;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类（重整版）
 * 继承org.apache.commons.lang.time.DateUtils类
 * 父类常用：isSameDay、parseDate、addYears、setYears、truncate等
 *
 * @author LinWang
 * @createTime 2017-2-28
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    private static final String SHORT_FORMAT = "yyyy-MM-dd";

    private static final String LONG_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private static final String TIME_FORMAT = "HH:mm:ss";

    private static final String WEEK_FORMAT = "E";

    private static final String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM", "MM/dd/yy HH:mm"};

    /**
     * 日期型字符串转化为Date
     * 解析时会逐个使用parsePatterns中的格式，如果都没有匹配上， 则抛出异常ParseException
     */
    public static Date parseDate(final Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * Date截取到短日期
     * @param date
     * @return
     * @throws Exception
     */
    public static Date trunc(final Date date) throws Exception {
        return parseDate(toShortStringFormat(date), SHORT_FORMAT);
    }

    /**
     * 得到当前日期字符串，格式（yyyy-MM-dd）
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @return
     */
    public static String getNowSimpleDate() {
        return getNowDate(SHORT_FORMAT);
    }

    /**
     * 得到当前日期字符串（根据指定格式）
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param pattern
     * @return
     */
    public static String getNowDate(final String pattern) {
        return DateFormatUtils.format(new Date(), pattern);
    }

    /**
     * Date转换成格式字符串(yyyy-MM-dd)
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param date
     * @return
     */
    public static String toShortStringFormat(final Date date) {
        return DateFormatUtils.format(date, SHORT_FORMAT);
    }

    /**
     * Date转换成格式字符串(yyyy-MM-dd HH:mm:ss)
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param date
     * @return
     */
    public static String toLongStringFormat(final Date date) {
        return DateFormatUtils.format(date, LONG_FORMAT);
    }

    /**
     * Date转换成时分秒字符串(HH:mm:ss)
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param date
     * @return
     */
    public static String toTimeStringFormat(final Date date) {
        return DateFormatUtils.format(date, TIME_FORMAT);
    }

    /**
     * Date转换成星期字符串(E)
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param date
     * @return
     */
    public static String toWeekStringFormat(final Date date) {
        return DateFormatUtils.format(date, WEEK_FORMAT);
    }

    /**
     * 日期加减方法（lang3已经封装）
     *
     * @author LinWang
     * @createTime 2017-2-28
     * @param date 需要改变的源日期数据
     * @param count 要加的数量，可能为负数
     * @param dateType 添加的类型，如年为Calendar.YEAR
     * @return
     * @throws Exception
     */
    public static Date addDate(final Date date, final int count, final int dateType) throws Exception {

        Date newDate = null;

        switch (dateType) {
            case Calendar.YEAR:
                newDate = addYears(date, count);
                break;
            case Calendar.MONTH:
                newDate = addMonths(date, count);
                break;
            case Calendar.DAY_OF_MONTH:
                newDate = addDays(date, count);
                break;
            default:
                throw new ApiException("请输入合法的类型！");
        }

        return newDate;
    }

    /**
     *转化为时分秒 a integer to xx:xx:xx
     * @param time
     * @return
     */
    public static String secToTime(int time) {
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;
        if (time <= 0)
            return "00:00";
        else {
            minute = time / 60;
            if (minute < 60) {
                second = time % 60;
                timeStr = unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                if (hour > 99)
                    return "99:59:59";
                minute = minute % 60;
                second = time - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
            }
        }
        return timeStr;
    }

    public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10)
            retStr = "0" + Integer.toString(i);
        else
            retStr = "" + i;
        return retStr;
    }

    /**
     * 计算日期间隔(日)
     * @param start
     * @param end
     * @return
     * @throws Exception
     */
    public static long betweenDays(final Date start, final Date end) throws Exception {
        return between(start, end, DateType.Days);
    }

    /**
     * 计算日期间隔
     * @param start
     * @param end
     * @param dateType
     * @return
     * @throws Exception
     */
    public static long between(final Date start, final Date end, final DateType dateType) throws Exception {
        long dividend = 1;
        switch (dateType) {
            case Days:
                dividend = 1000 * 60 * 60 * 24;
                break;
            case Hours:
                dividend = 1000 * 60 * 60;
                break;
            case Minutes:
                dividend = 1000 * 60;
                break;
            case Seconds:
                dividend = 1000;
                break;
            case Milliseconds:
                dividend = 1;
                break;
            default:
                throw new ApiException("无效的日期类型枚举值！");
        }
        return (end.getTime() - start.getTime()) / dividend;
    }

    /**
     * 获取过去的天数
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取过去的小时
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (60 * 60 * 1000);
    }

    /**
     * 获取过去的分钟
     * @param date
     * @return
     */
    public static long pastMinutes(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 日期类型枚举
     * @author Sugar
     *
     */
    public enum DateType {
        /**
         * 日
         */
        Days,

        /**
         * 小时
         */
        Hours,

        /**
         * 分钟
         */
        Minutes,

        /**
         * 秒
         */
        Seconds,

        /**
         * 毫秒
         */
        Milliseconds
    }

    /**
     * @param args
     * @throws ParseException
     */
    public static void main(String[] args) throws ParseException {

        Date date = new Date();
        System.out.println(DateUtils.truncate(date, Calendar.HOUR));
    }
}
